package org.example.service;

import org.example.entity.CustomerOrder;
import org.example.entity.CustomerRepayPlan;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Vintage和迁徙率计算服务
 */
@Service
public class VintageMigrationService {
    
    // 迁徙率配置（M1->M2, M2->M3, M3->M4等）
    private static final Map<String, Double> MIGRATION_RATES = Map.of(
        "M1_M2", 0.25,  // M1到M2的迁徙率25%
        "M2_M3", 0.35,  // M2到M3的迁徙率35%
        "M3_M4", 0.45,  // M3到M4的迁徙率45%
        "M4_M5", 0.55,  // M4到M5的迁徙率55%
        "M5_M6", 0.65   // M5到M6的迁徙率65%
    );
    
    // Vintage逾期率目标（控制在5%左右）
    private static final Map<String, Double> VINTAGE_TARGET_RATES = Map.of(
        "0+", 0.08,   // 0+逾期率8%
        "30+", 0.06,  // 30+逾期率6%
        "60+", 0.05,  // 60+逾期率5%
        "90+", 0.045  // 90+逾期率4.5%
    );
    
    /**
     * 计算迁徙率
     * @param fromBucket 源逾期区间（如M1）
     * @param toBucket 目标逾期区间（如M2）
     * @param fromAmount 源区间金额
     * @return 迁徙金额
     */
    public BigDecimal calculateMigrationAmount(String fromBucket, String toBucket, BigDecimal fromAmount) {
        String key = fromBucket + "_" + toBucket;
        Double rate = MIGRATION_RATES.get(key);
        if (rate == null) {
            return BigDecimal.ZERO;
        }
        
        // 添加随机波动（±10%）
        double randomFactor = 0.9 + ThreadLocalRandom.current().nextDouble() * 0.2;
        double finalRate = rate * randomFactor;
        
        return fromAmount.multiply(BigDecimal.valueOf(finalRate)).setScale(2, RoundingMode.HALF_UP);
    }
    
    /**
     * 计算Vintage逾期率
     * @param vintageDate Vintage日期
     * @param observationDate 观察日期
     * @param orders 该Vintage的所有订单
     * @param repayPlans 对应的还款计划
     * @return Vintage逾期率统计
     */
    public VintageStats calculateVintageStats(LocalDate vintageDate, LocalDate observationDate, 
                                            List<CustomerOrder> orders, List<CustomerRepayPlan> repayPlans) {
        
        // 计算Vintage初始发放总额
        BigDecimal initialAmount = orders.stream()
                .map(CustomerOrder::getLoanAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 计算各逾期区间的余额
        Map<String, BigDecimal> overdueBalances = calculateOverdueBalances(orders, repayPlans, observationDate);
        
        // 计算各逾期率
        Map<String, Double> overdueRates = new HashMap<>();
        for (Map.Entry<String, BigDecimal> entry : overdueBalances.entrySet()) {
            String bucket = entry.getKey();
            BigDecimal balance = entry.getValue();
            double rate = initialAmount.compareTo(BigDecimal.ZERO) > 0 ? 
                    balance.divide(initialAmount, 4, RoundingMode.HALF_UP).doubleValue() * 100 : 0.0;
            overdueRates.put(bucket, rate);
        }
        
        return new VintageStats(vintageDate, observationDate, initialAmount, overdueBalances, overdueRates);
    }
    
    /**
     * 计算各逾期区间的余额
     */
    private Map<String, BigDecimal> calculateOverdueBalances(List<CustomerOrder> orders, 
                                                           List<CustomerRepayPlan> repayPlans, 
                                                           LocalDate observationDate) {
        Map<String, BigDecimal> balances = new HashMap<>();
        balances.put("0+", BigDecimal.ZERO);
        balances.put("30+", BigDecimal.ZERO);
        balances.put("60+", BigDecimal.ZERO);
        balances.put("90+", BigDecimal.ZERO);
        
        // 按订单分组还款计划
        Map<String, List<CustomerRepayPlan>> orderRepayPlans = repayPlans.stream()
                .collect(java.util.stream.Collectors.groupingBy(CustomerRepayPlan::getOrderNo));
        
        for (CustomerOrder order : orders) {
            List<CustomerRepayPlan> plans = orderRepayPlans.getOrDefault(order.getOrderNo(), new ArrayList<>());
            BigDecimal orderOverdueBalance = calculateOrderOverdueBalance(order, plans, observationDate);
            
            if (orderOverdueBalance.compareTo(BigDecimal.ZERO) > 0) {
                long overdueDays = calculateOverdueDays(order, plans, observationDate);
                
                if (overdueDays > 0) {
                    balances.put("0+", balances.get("0+").add(orderOverdueBalance));
                }
                if (overdueDays > 30) {
                    balances.put("30+", balances.get("30+").add(orderOverdueBalance));
                }
                if (overdueDays > 60) {
                    balances.put("60+", balances.get("60+").add(orderOverdueBalance));
                }
                if (overdueDays > 90) {
                    balances.put("90+", balances.get("90+").add(orderOverdueBalance));
                }
            }
        }
        
        return balances;
    }
    
    /**
     * 计算订单的逾期余额
     */
    private BigDecimal calculateOrderOverdueBalance(CustomerOrder order, List<CustomerRepayPlan> plans, LocalDate observationDate) {
        // 计算已到期但未还的金额
        BigDecimal overdueAmount = BigDecimal.ZERO;
        
        for (CustomerRepayPlan plan : plans) {
            if (plan.getDueDate().isBefore(observationDate) || plan.getDueDate().isEqual(observationDate)) {
                if (plan.getActualRepayMoney() == null || plan.getActualRepayMoney().compareTo(plan.getNowPayAmount()) < 0) {
                    BigDecimal unpaidAmount = plan.getNowPayAmount().subtract(
                            plan.getActualRepayMoney() != null ? plan.getActualRepayMoney() : BigDecimal.ZERO);
                    overdueAmount = overdueAmount.add(unpaidAmount);
                }
            }
        }
        
        return overdueAmount;
    }
    
    /**
     * 计算逾期天数
     */
    private long calculateOverdueDays(CustomerOrder order, List<CustomerRepayPlan> plans, LocalDate observationDate) {
        if (plans.isEmpty()) {
            return 0;
        }
        
        // 找到最早逾期的还款计划
        LocalDate earliestOverdueDate = null;
        for (CustomerRepayPlan plan : plans) {
            if (plan.getDueDate().isBefore(observationDate) || plan.getDueDate().isEqual(observationDate)) {
                if (plan.getActualRepayMoney() == null || plan.getActualRepayMoney().compareTo(plan.getNowPayAmount()) < 0) {
                    if (earliestOverdueDate == null || plan.getDueDate().isBefore(earliestOverdueDate)) {
                        earliestOverdueDate = plan.getDueDate();
                    }
                }
            }
        }
        
        if (earliestOverdueDate != null) {
            return ChronoUnit.DAYS.between(earliestOverdueDate, observationDate);
        }
        
        return 0;
    }
    
    /**
     * 根据迁徙率生成逾期状态
     * @param currentStatus 当前逾期状态
     * @param overdueDays 逾期天数
     * @return 新的逾期状态
     */
    public String generateMigrationStatus(String currentStatus, long overdueDays) {
        if (overdueDays <= 0) {
            return "正常";
        } else if (overdueDays <= 30) {
            return "M1";
        } else if (overdueDays <= 60) {
            return "M2";
        } else if (overdueDays <= 90) {
            return "M3";
        } else if (overdueDays <= 120) {
            return "M4";
        } else if (overdueDays <= 150) {
            return "M5";
        } else {
            return "M6+";
        }
    }
    
    /**
     * 判断是否发生迁徙
     * @param fromStatus 源状态
     * @param toStatus 目标状态
     * @return 是否迁徙
     */
    public boolean shouldMigrate(String fromStatus, String toStatus) {
        String key = fromStatus + "_" + toStatus;
        Double rate = MIGRATION_RATES.get(key);
        if (rate == null) {
            return false;
        }
        
        return ThreadLocalRandom.current().nextDouble() < rate;
    }
    
    /**
     * Vintage统计结果
     */
    public static class VintageStats {
        private final LocalDate vintageDate;
        private final LocalDate observationDate;
        private final BigDecimal initialAmount;
        private final Map<String, BigDecimal> overdueBalances;
        private final Map<String, Double> overdueRates;
        
        public VintageStats(LocalDate vintageDate, LocalDate observationDate, BigDecimal initialAmount,
                          Map<String, BigDecimal> overdueBalances, Map<String, Double> overdueRates) {
            this.vintageDate = vintageDate;
            this.observationDate = observationDate;
            this.initialAmount = initialAmount;
            this.overdueBalances = overdueBalances;
            this.overdueRates = overdueRates;
        }
        
        // Getters
        public LocalDate getVintageDate() { return vintageDate; }
        public LocalDate getObservationDate() { return observationDate; }
        public BigDecimal getInitialAmount() { return initialAmount; }
        public Map<String, BigDecimal> getOverdueBalances() { return overdueBalances; }
        public Map<String, Double> getOverdueRates() { return overdueRates; }
        
        @Override
        public String toString() {
            return String.format("Vintage[%s] 观察时点[%s] 初始金额[%s] 逾期率[0+:%.2f%%, 30+:%.2f%%, 60+:%.2f%%, 90+:%.2f%%]",
                    vintageDate, observationDate, initialAmount,
                    overdueRates.getOrDefault("0+", 0.0),
                    overdueRates.getOrDefault("30+", 0.0),
                    overdueRates.getOrDefault("60+", 0.0),
                    overdueRates.getOrDefault("90+", 0.0));
        }
    }
}
